import * as Cesium from 'cesium';
function Entities(viewer) {
    this.viewer = viewer;
}

/**
 * @description: 添加点(单个)
 * @param {*} entityObj
 * coordinates 坐标,必传 格式[x,y,z]
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}entity 返回相关实体，便于从后续对实体进行操作
 */
Entities.prototype.addPoint = function (entityObj) {
    const coordinates = entityObj.coordinates;
    const styleObj = entityObj.style || {};
    const markerInfo = entityObj.info;
    const cartesian = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], coordinates[2] || 0);

    const entity = this.viewer.entities.add({
        position: cartesian,
        point: {
            pixelSize: styleObj.pixelSize || 10,
            color: styleObj.color || Cesium.Color.RED
        }
    });

    if (markerInfo) {
        entity[markerInfo.name] = markerInfo.info;
    }

    return entity;
};

/**
 * @description: 添加图标点(单个)
 * @param {*} entityObj
 * coordinates 坐标,必传 格式[x,y,z]
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}entity 返回相关实体，便于从后续对实体进行操作
 */
Entities.prototype.addBillboard = function (entityObj) {
    const coordinates = entityObj.coordinates;
    const styleObj = entityObj.style || {};
    const markerInfo = entityObj.info;
    const cartesian = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], coordinates[2] || 0);

    // 创建点的实例
    const entity = this.viewer.entities.add({
        position: cartesian,
        billboard: {
            image: styleObj.src,
            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
            width: styleObj.width || 20,
            height: styleObj.height || 20
        }
    });

    if (markerInfo) {
        entity[markerInfo.name] = markerInfo.info;
    }

    return entity;
};

/**
 * @description: 添加文本标签(单个)
 * @param {*} entityObj
 * coordinates 坐标,必传 格式[x,y,z]
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}entity 返回相关实体，便于从后续对实体进行操作
 */
Entities.prototype.addLabel = function (entityObj) {
    const coordinates = entityObj.coordinates;
    const styleObj = entityObj.style || {};
    const markerInfo = entityObj.info;
    const cartesian = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], coordinates[2] || 0);

    const entity = this.viewer.entities.add({
        position: cartesian,
        label: {
            text: styleObj.text || 'Cesium Label',
            font: styleObj.font || '20px sans-serif',
            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
            outlineColor: styleObj.outlineColor || Cesium.Color.BLACK,
            verticalOrigin: Cesium.VerticalOrigin.BOTTOM
        }
    });

    if (markerInfo) {
        entity[markerInfo.name] = markerInfo.info;
    }

    return entity;
};

/**
 * @description: 添加折线(单个)
 * @param {*} entityObj
 * coordinates 坐标,必传 格式[110.14170, 22.66112, 111.14170, 23.66112]
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}entity 返回相关实体，便于从后续对实体进行操作
 */
Entities.prototype.addPolyline = function (entityObj) {
    const coordinates = entityObj.coordinates;
    const styleObj = entityObj.style || {};
    const markerInfo = entityObj.info;

    const entity = this.viewer.entities.add({
        polyline: {
            positions: Cesium.Cartesian3.fromDegreesArray(coordinates),
            width: styleObj.width || 10,
            material: styleObj.material || Cesium.Color.BLUE
        }
    });

    if (markerInfo) {
        entity[markerInfo.name] = markerInfo.info;
    }

    return entity;
};

/**
 * @description: 添加多边形(单个)
 * @param {*} entityObj
 * coordinates 坐标,必传 格式[[110.14170, 22.66112], [110.14170, 22.66756], [110.13942, 22.67091], [110.13593, 22.67373], [110.13030, 22.67399], [110.12695, 22.66729], [110.12829, 22.66394], [110.13178, 22.66086], [110.14170, 22.66112]]
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}entity 返回相关实体，便于从后续对实体进行操作
 */
Entities.prototype.addPolygon = function (entityObj) {
    const coordinates = entityObj.coordinates;
    const styleObj = entityObj.style || {};
    const markerInfo = entityObj.info;

    const cartesianArray = coordinates.map((coord) => {
        return Cesium.Cartesian3.fromDegrees(coord[0], coord[1], coord[2] || 0);
    });
    const entity = this.viewer.entities.add({
        polygon: {
            hierarchy: new Cesium.PolygonHierarchy(cartesianArray),
            material: styleObj.material || Cesium.Color.MAGENTA.withAlpha(0.5)
        }
    });

    if (markerInfo) {
        entity[markerInfo.name] = markerInfo.info;
    }

    return entity;
};

/**
 * @description: 添加矩形(单个)
 * @param {*} entityObj
 * coordinates 坐标,必传 格式[110.14170, 22.66112, 111.14170, 23.66112]
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}entity 返回相关实体，便于从后续对实体进行操作
 */
Entities.prototype.addRectangle = function (entityObj) {
    const coordinates = entityObj.coordinates;
    const styleObj = entityObj.style || {};
    const markerInfo = entityObj.info;

    const entity = this.viewer.entities.add({
        rectangle: {
            coordinates: Cesium.Rectangle.fromDegrees(coordinates[0], coordinates[1], coordinates[2], coordinates[3]),
            extrudedHeight: styleObj.extrudedHeight || 30,
            height: styleObj.height || 10,
            outline: styleObj.outline || false,
            outlineColor: styleObj.outlineColor || Cesium.Color.BLACK,
            material: styleObj.material || Cesium.Color.GREEN.withAlpha(0.5)
        }
    });

    if (markerInfo) {
        entity[markerInfo.name] = markerInfo.info;
    }

    return entity;
};

/**
 * @description: 添加3D 模型(单个)
 * @param {*} entityObj
 * coordinates 坐标,必传 格式[x,y,z]
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}entity 返回相关实体，便于从后续对实体进行操作
 */
Entities.prototype.addModel = function (entityObj) {
    const coordinates = entityObj.coordinates;
    const styleObj = entityObj.style || {};
    const markerInfo = entityObj.info;
    const cartesian = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], coordinates[2] || 0);

    // 定义模型的朝向角度（航向角、俯仰角、翻滚角）
    const heading = Cesium.Math.toRadians(styleObj.heading || 135); // 航向角，135度，转换为弧度
    const pitch = styleObj.pitch || 0; // 俯仰角，0度，表示模型没有上下倾斜
    const roll = styleObj.roll || 0; // 翻滚角，0度，表示模型没有左右翻滚

    // 创建一个航向-俯仰-翻滚对象（HeadingPitchRoll）
    const hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);

    // 将航向-俯仰-翻滚对象转换为四元数（Quaternion），用于表示模型的旋转
    const orientation = Cesium.Transforms.headingPitchRollQuaternion(cartesian, hpr);

    const entity = this.viewer.entities.add({
        position: cartesian,
        orientation: orientation,
        model: {
            uri: styleObj.uri,
            minimumPixelSize: styleObj.minimumPixelSize || 128, // 模型在屏幕上的最小像素大小，确保模型在远处也能清晰可见
            maximumScale: styleObj.maximumScale || 2000 // 模型的最大缩放比例，控制模型的最大显示大小
        }
    });

    if (markerInfo) {
        entity[markerInfo.name] = markerInfo.info;
    }

    return entity;
};

/**
 * @description: 添加三维立方体(单个)
 * @param {*} entityObj
 * coordinates 坐标,必传 格式[x,y,z]
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}entity 返回相关实体，便于从后续对实体进行操作
 */
Entities.prototype.addBox = function (entityObj) {
    const coordinates = entityObj.coordinates;
    const styleObj = entityObj.style || {};
    const markerInfo = entityObj.info;
    const cartesian = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], coordinates[2] || 0);

    const entity = this.viewer.entities.add({
        position: cartesian,
        box: {
            dimensions: new Cesium.Cartesian3(styleObj.size[0] || 100, styleObj.size[1] || 100, styleObj.size[2] || 50), // 长、宽、高
            material: styleObj.material || Cesium.Color.RED.withAlpha(0.5)
        }
    });

    if (markerInfo) {
        entity[markerInfo.name] = markerInfo.info;
    }

    return entity;
};

/**
 * @description: 添加三维圆柱体(单个)
 * @param {*} entityObj
 * coordinates 坐标,必传 格式[x,y,z]
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}entity 返回相关实体，便于从后续对实体进行操作
 */
Entities.prototype.addCylinder = function (entityObj) {
    const coordinates = entityObj.coordinates;
    const styleObj = entityObj.style || {};
    const markerInfo = entityObj.info;
    const cartesian = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], coordinates[2] || 0);

    const entity = this.viewer.entities.add({
        position: cartesian,
        cylinder: {
            length: styleObj.length || 20000, // 高度
            topRadius: styleObj.topRadius || 5000, // 顶部半径
            bottomRadius: styleObj.bottomRadius || 5000, // 底部半径
            material: styleObj.material || Cesium.Color.GREEN.withAlpha(0.5)
        }
    });

    if (markerInfo) {
        entity[markerInfo.name] = markerInfo.info;
    }

    return entity;
};

/**
 * @description: 添加三维椭圆(单个)
 * @param {*} entityObj
 * coordinates 坐标,必传 格式[x,y,z]
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}entity 返回相关实体，便于从后续对实体进行操作
 */
Entities.prototype.addEllipse = function (entityObj) {
    const coordinates = entityObj.coordinates;
    const styleObj = entityObj.style || {};
    const markerInfo = entityObj.info;
    const cartesian = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], coordinates[2] || 0);

    const entity = this.viewer.entities.add({
        position: cartesian,
        ellipse: {
            semiMajorAxis: styleObj.semiMajorAxis || 100, // 长轴
            semiMinorAxis: styleObj.semiMinorAxis || 50, // 短轴
            material: styleObj.material || Cesium.Color.YELLOW.withAlpha(0.5)
        }
    });

    if (markerInfo) {
        entity[markerInfo.name] = markerInfo.info;
    }

    return entity;
};

/**
 * @description: 添加三维椭球体(单个)
 * @param {*} entityObj
 * coordinates 坐标,必传 格式[x,y,z]
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}entity 返回相关实体，便于从后续对实体进行操作
 */
Entities.prototype.addEllipsoid = function (entityObj) {
    const coordinates = entityObj.coordinates;
    const styleObj = entityObj.style || {};
    const markerInfo = entityObj.info;
    const cartesian = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], coordinates[2] || 0);

    const entity = this.viewer.entities.add({
        position: cartesian,
        ellipsoid: {
            radii: new Cesium.Cartesian3(styleObj.size[0] || 100, styleObj.size[1] || 100, styleObj.size[2] || 50), // 长、宽、高
            material: styleObj.material || Cesium.Color.CYAN.withAlpha(0.5)
        }
    });

    if (markerInfo) {
        entity[markerInfo.name] = markerInfo.info;
    }

    return entity;
};

/**
 * @description: 添加三维走廊或管道(单个)
 * @param {*} entityObj
 * coordinates 坐标,必传 格式[110, 22, 111, 22, 111, 23]
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}entity 返回相关实体，便于从后续对实体进行操作
 */
Entities.prototype.addCorridor = function (entityObj) {
    const coordinates = entityObj.coordinates;
    const styleObj = entityObj.style || {};
    const markerInfo = entityObj.info;

    const entity = this.viewer.entities.add({
        corridor: new Cesium.CorridorGraphics({
            extrudedHeight: styleObj.extrudedHeight || 10000,
            height: styleObj.height || 1000,
            width: styleObj.width || 5000,
            material: styleObj.material || Cesium.Color.RED.withAlpha(0.5), // 半透明白色填充
            outline: styleObj.outline || false, // 显示轮廓
            outlineColor: styleObj.outlineColor || Cesium.Color.BLACK, // 轮廓颜色为黑色
            outlineWidth: styleObj.outlineWidth || 2.0, // 轮廓宽度为 2 像素
            positions: Cesium.Cartesian3.fromDegreesArray(coordinates)
        })
    });

    if (markerInfo) {
        entity[markerInfo.name] = markerInfo.info;
    }

    return entity;
};

/**
 * @description: 添加三维墙(单个)
 * @param {*} entityObj
 * coordinates 坐标,必传 格式[110, 22, 111, 22, 111, 23]
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}entity 返回相关实体，便于从后续对实体进行操作
 */
Entities.prototype.addWall = function (entityObj) {
    const coordinates = entityObj.coordinates;
    const styleObj = entityObj.style || {};
    const markerInfo = entityObj.info;

    const entity = this.viewer.entities.add({
        wall: {
            positions: Cesium.Cartesian3.fromDegreesArray(coordinates),
            minimumHeights: new Array(coordinates.length / 2).fill(styleObj.minimumHeights || 0), // 底部高度
            maximumHeights: new Array(coordinates.length / 2).fill(styleObj.maximumHeights || 1000), // 顶部高度
            material: styleObj.material || Cesium.Color.fromCssColorString('rgba(80, 211, 255, 0.4)')
        }
    });

    if (markerInfo) {
        entity[markerInfo.name] = markerInfo.info;
    }

    return entity;
};

/**
 * @description: 添加三维折线体积(管道)(单个)
 * @param {*} entityObj
 * coordinates 坐标,必传 格式[110, 22, 111, 22, 111, 23]
 * style 样式对象
 * markerInfo{name:xxx,info:xxx} marker的属性信息,name为属性名，info为属性值，用于给不同矢量添加弹窗信息
 * @return {*}entity 返回相关实体，便于从后续对实体进行操作
 */
Entities.prototype.addPolylineVolume = function (entityObj) {
    const coordinates = entityObj.coordinates;
    const styleObj = entityObj.style || {};
    const markerInfo = entityObj.info;

    const entity = this.viewer.entities.add({
        polylineVolume: {
            positions: Cesium.Cartesian3.fromDegreesArray(coordinates),
            shape: computeCircle(styleObj.radius || 1),
            material: styleObj.material || Cesium.Color.RED.withAlpha(0.5),
            cornerType: Cesium.CornerType[styleObj.cornerType || 'ROUNDED'] //ROUNDED MITERED BEVELED
        }
    });

    if (markerInfo) {
        entity[markerInfo.name] = markerInfo.info;
    }

    return entity;
};
function computeCircle(radius) {
    const positions = [];
    for (let i = 0; i < 360; i++) {
        const radians = Cesium.Math.toRadians(i);
        positions.push(new Cesium.Cartesian2(radius * Math.cos(radians), radius * Math.sin(radians)));
    }
    return positions;
}

/**
 * @description: 添加3D Tiles 数据集
 * @param {*} url
 * @return {*}
 */
Entities.prototype.addTileset = function (url) {
    let tileset = this.viewer.scene.primitives.add(new Cesium.Cesium3DTileset({ url: url }));
    this.viewer.scene.globe.depthTestAgainstTerrain = true;
    tileset.readyPromise.then(function (tileset) {
        let boundingSphere = tileset.boundingSphere; // 模型的范围
        let cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center); // 从笛卡尔位置创建一个新的位置实例（返回的是一个经纬度的）
        let surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0); // 以经纬度的值来返回Cartesian3(xyz)的位置 ，/
        let offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 50); // 以经纬度的值来返回Cartesian3(xyz)的位置 ，//>
        let translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3()); // 计算两个笛卡尔的分量差异。
        tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
        this.viewer.zoomTo(tileset);
    });
};

export default Entities;
